Skip to content

Add a draft security threat model (THREAT_MODEL.md) + SECURITY.md + discoverability wiring#1224

Open
potiuk wants to merge 1 commit into
apache:mainfrom
potiuk:asf-security/threat-model-2026-07-04
Open

Add a draft security threat model (THREAT_MODEL.md) + SECURITY.md + discoverability wiring#1224
potiuk wants to merge 1 commit into
apache:mainfrom
potiuk:asf-security/threat-model-2026-07-04

Conversation

@potiuk

@potiuk potiuk commented Jul 4, 2026

Copy link
Copy Markdown
Member

This is a proposal for the Guacamole PMC to review — please correct, reject, or discuss as needed. The PMC owns the document; nothing here is a requirement.

This adds a draft umbrella THREAT_MODEL.md for the Apache Guacamole family, a SECURITY.md (the code repos don't currently carry one — the security policy lives only at guacamole.apache.org/security), and an AGENTS.md wiring AGENTS.md -> SECURITY.md -> THREAT_MODEL.md so an automated scanner can mechanically discover it. Path 3 as agreed on the list (we draft the v0, the PMC reviews). It lands on apache/guacamole-client as the canonical home; guacamole-server and guacamole-website get small pointer PRs to it once you're happy with the shape.

Generated from Guacamole's public artefacts (the security page, docs, advisory history) via the threat-model-producer rubric. Provenance-tagged throughout; every (inferred) claim routes to a numbered §14 question (15 of them).

The model's spine is the guacd(C) / client(Java) / website(static) split:

  • guacd + libguac + the C protocol plugins are modeled as the primary memory-safety surface — untrusted data from the remote desktop server flowing back into C parsers (anchored to the real CVE history: the 2020 "Reverse RDP" set, the VNC/RDP/SSH parsing CVEs);
  • guacamole-client as the authn/authz + tunnel surface;
  • guacamole-website is explicitly out of model for runtime findings, in scope only for discoverability.

Two calls we'd especially value your confirmation on (both in §14 wave 1): (1) guacd is not an auth boundary and must be kept off untrusted networks — a report against an exposed :4822 is a misconfiguration, not an in-model bug; (2) the plaintext/unauthenticated webapp↔guacd default (guacd-ssl off on a trusted segment) as the supported production posture.

What's most useful: walk the §14 questions and confirm / correct / strike each — a one-liner each is enough. This PR only adds files; it edits no existing content.

Context: the ASF Security team is preparing projects for an automated agentic security scan we're piloting; discoverability is the one hard prerequisite.

…iscoverability wiring

Generated-by: Claude Code
Comment thread THREAT_MODEL.md

| Family | Repo | Language | Representative entry point | Touches outside the process? | In model? |
| --- | --- | --- | --- | --- | --- |
| **guacd core + libguac** | guacamole-server | C | TCP `:4822`, Guacamole-protocol parser, plugin loader | Yes — outbound TCP to remote servers; loads `.so` plugins | **Yes** — primary memory-safety surface |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we specify the incoming connection from guacamole-client?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it should call out the inbound connection specifically from guacamole-client, since we do advertise/support it as a more generic Guacamole Protocol proxy that can support custom front-ends, but inbound from a client is probably worth noting.

@necouchman necouchman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, several comments from me - apologies in advance if any of these are nonsensical.

Comment thread THREAT_MODEL.md
be modeled separately because they live at very different trust levels and are
written in different languages: **guacd**, a C daemon (`apache/guacamole-server`)
that actually speaks the remote-desktop protocols and translates them to and from
the text-based *Guacamole protocol*; and the **web application**, a Java servlet

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is text-based the best wording, here? I ask because, while we do deliver most of the protocol over text, we also deliver images??

Comment thread THREAT_MODEL.md
Comment on lines +80 to +81
*(documented — introduction)*. Guacamole is a *deployed network service operated
by an administrator*, not an in-process library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this captures the overall scope of the project, I wonder how this statement applies to folks who use the libguac portion of the guacamole-server project, or the guacamole-common and guacamole-common-js portions of the guacamole-client project? How does the fact that we do provide those as libraries that can be used by third party projects relate to our documentation of the thread model?

Comment thread THREAT_MODEL.md
*(inferred — I6)*.
- **guacd exposed directly to untrusted networks.** guacd is designed to sit behind
the web app on a trusted network segment; a deployment that publishes `:4822` to
the Internet is a misconfiguration, not a scenario we defend (see §9, §10)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would replace the Internet with any un-trusted network or something similar - while the Internet may be the ultimate example of an un-trusted network, it is certainly not the only example, and publishing guacd port 4822 to any users or systems that should not have direct proxy access through guacd to your remote systems is a violation of the design principles of the software.

Comment thread THREAT_MODEL.md
Comment on lines +152 to +154
browser ──HTTPS/tunnel──▶ web app (Java) ──TCP :4822──▶ guacd (C) ──RDP/VNC/SSH──▶ remote server
▲ │
└───────────── Guacamole protocol (rendered images/audio/clipboard) ◀──────────────────────┘

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not quite accurate - I don't know how much it matters, but, taken at face value, this states that the remote server will speak Guacamole protocol directly to the user's browser, which is not how it works. I'm not entirely sure how to diagram this best in a Github comment, but:

  • All traffic from the user's browser passes through the HTTP(S)/WS(S) tunnel back to the Java application, which handles both API calls used for authentication, authorization, and auditing, but also handles the establishment and maintenance of the HTTP(S)/WS(S) tunnel back to guacd. The only traffic that the user's browser will ever see will be between it and the Web Application host(s).
  • The traffic to/from the user's browser, tunneled over HTTP(S)/WS(S) by the web application will land at the guacd application, which does all of the translation between the Guacamole protocol and the remote protocols.
  • The remote server will only ever see traffic from and send traffic to the guacd instance - there is no direct path from the remote server back to the user's browser. That traffic traverses the same path back - from remote server to guacd, then from guacd back through the tunnel maintenance by the web application, where it is then delivered to the user's browser.

Comment thread THREAT_MODEL.md
Comment on lines +176 to +178
4. **guacd/web app → identity & storage backends.** LDAP/SAML/DB/RADIUS lookups
during authentication, and connection-credential storage/retrieval *(documented
— introduction lists the extensions; inferred as to trust treatment — I9)*.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slight clarification, here - guacd does not store anything outside of memory. The only credential lookups and storage are done by the web application, which 1) authenticates the users, 2) provides authorization for connections, 3) documents the connections, 4) stores and looks up connection details, potentially including credentials, 5) requests additional credentials from the user, when required, and then 6) delivers the connection information to guacd. guacd only "stores" any of this information in-memory, and only for the duration of the connection, after which it is discarded.

Comment thread THREAT_MODEL.md
Comment on lines +543 to +545
11. **(I18) `guacd-ssl` provides transport encryption but not, by itself, mutual
authentication of the web app to guacd (false friend).** Proposed: correct —
confirm whether any mutual-auth mechanism exists on this link. *Lands in §9.*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct - there is currently no mutual authentication implemented native to the web app <-> guacd components. It can be implemented with, for example, SSH or SSL tunneling configured with additional components, but that is out of scope of this model.

Comment thread THREAT_MODEL.md
Comment on lines +546 to +550
12. **(I11/I13) guacd runs as a forking POSIX daemon, does not treat environment
variables as a trust input, does not phone home, and confines outbound
connections to operator-defined targets; guacd and the web app are expected to
run matching patched versions.** Proposed: correct — this negative-side-effects
inventory is the one most needing maintainer confirmation. *Lands in §5.*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct...mostly...I think. We do support running different versions of web application and guacd, and have built in some mechanisms to handle negotiation of features between those versions; however, this is strictly designed to handle feature differences, and no guarantee is provided that doing so will be "safe".

Comment thread THREAT_MODEL.md
Comment on lines +551 to +555
13. **(I17) Resource guarantees: is there *any* categorical line on DoS from a
hostile remote stream or a client opening many tunnels — e.g. "a crash/UAF is a
bug, but sustained CPU/bandwidth from a connected server is not"?** Proposed: no
categorical resource guarantee at this layer; memory-safety failures remain
bugs. *Lands in §8/§9/§11a.*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not believe there are any resource guarantees at this time - it is up to the operator to monitor and throttle resource utilization.

Comment thread THREAT_MODEL.md
Comment on lines +556 to +559
14. **(I7/I10) Third-party protocol libraries (FreeRDP/libVNCserver/libssh2/Cairo,
bundled JS) are modeled only at the boundary where we hand them data; internal
CVEs are triaged upstream. Reachability preconditions per §4 are the triage
test.** Proposed: correct. *Lands in §3/§4.*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

Comment thread THREAT_MODEL.md
Comment on lines +563 to +568
15. **Document ownership & coexistence.** There is currently **no `SECURITY.md` in
either code repository** — the sole published security artifact is the website
security page. Proposed: this threat model becomes the canonical model that the
security page (and new `SECURITY.md` files in both repos) link to. Confirm the
venue and whether the PMC wants the machine-readable §15 sidecar. *Meta — no
body claim.*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with the proposed solution, but ultimately will leave it to @mike-jumper to decide on that.

@necouchman necouchman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, several comments from me - apologies in advance if any of these are nonsensical.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants